/*
 * Copyright (c) 2013, SRI International
 * All rights reserved.
 * Licensed under the The BSD 3-Clause License;
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at:
 * 
 * http://opensource.org/licenses/BSD-3-Clause
 * 
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 
 * Redistributions of source code must retain the above copyright
 * notice, this list of conditions and the following disclaimer.
 * 
 * Redistributions in binary form must reproduce the above copyright
 * notice, this list of conditions and the following disclaimer in the
 * documentation and/or other materials provided with the distribution.
 * 
 * Neither the name of the aic-web-praise nor the names of its
 * contributors may be used to endorse or promote products derived from
 * this software without specific prior written permission.
 * 
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
 * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, 
 * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES 
 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
 * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
 * OF THE POSSIBILITY OF SUCH DAMAGE.
 */
package com.sri.ai.lpitools.gwtgui.client.components.editor;

//import java.util.List;

import com.google.gwt.core.client.JavaScriptObject;
import com.google.gwt.event.logical.shared.AttachEvent;
import com.google.gwt.event.logical.shared.AttachEvent.Handler;
import com.sri.ai.lpitools.cobra.gwtutil.dataobjects.shared.ModelInfo;
//import com.sri.ai.lpitools.cobra.gwtutil.dataobjects.shared.ModelObject;
import com.sri.ai.lpitools.gwtgui.client.components.manager.ModelListener;
import com.sri.ai.lpitools.gwtgui.client.components.manager.ModelManager;

import edu.ycp.cs.dh.acegwt.client.ace.AceEditor;
import edu.ycp.cs.dh.acegwt.client.ace.AceEditorCallback;
import edu.ycp.cs.dh.acegwt.client.ace.AceEditorMode;
import edu.ycp.cs.dh.acegwt.client.ace.AceEditorTheme;

/**
 * This class is an extension of the AceEditor that 
 * supports the formatting of server-supplied model strings.
 * 
 * Several things must be done in order to use this class in a GWT project.
 * 
 * First, the edu.ycp.cs.dh.acegwt packages must be in a source folder.
 * They provide the gwt functionality.
 * 
 * Second, in the main html file for the GWT project, the following must be added to the <head> section.
 * 
 * <script src="acegwttest/ace/ace.js" type="text/javascript" charset="utf-8"></script>
 * <script src="acegwttest/ace/theme-eclipse.js" type="text/javascript" charset="utf-8"></script>
 * <script src="acegwttest/ace/mode-lpimodel.js" type="text/javascript" charset="utf-8"></script>
 *
 * Where acegwttest is replaced by the <module rename-to> value from the GWT.xml file, if there is one.
 * If there isn't one, it should be replaced by the fully qualified Module name, i.e. com.example.ModuleName.
 * theme-eclipse can be replaced by the name of the javascript file describing the theme you wish to use,
 * some themes are provided by ACEGWT and can be found in com.edu.ycp.cs.dh.acegwt/public/ace.
 * 
 * More than one theme tag can be present, as the theme is decided at the initialization of the editor.
 * 
 * The final step to be done to use this editor is to add to the project's gwt.xml file the line
 * 
 * <inherits name='edu.ycp.cs.dh.acegwt.AceGWT'/>
 * 
 * Once this has been done, the project is ready to use the ModelEditor.
 * 
 * To instantiate the editor, something along the lines of the following should be done.
 * 
 * <code>
 * 
 * // Instantiate Editor
 * ModelEditor editor = new ModelEditor();
 * // Set the width of the client. (If necessary)
 * editor.setWidth(Window.getClientWidth() + "px");
 * // Set the height of the editor. (If necessary)
 * editor.setHeight(Window.getClientHeight() + "px");
 * // Add editor to it's panel.
 * RootPanel.get().add(editor);
 * // Start the editor.
 * editor.startEditor();
 * // Set the mode of the editor to edit LPI Models.
 * editor.setMode(AceEditorMode.LPIMODEL);
 * // Set the theme of the editor. (Selected theme must have been added as a script tag as specified above.)
 * editor.setTheme(AceEditorTheme.ECLIPSE);
 * 
 * </code>
 * 
 * @author dabraham
 *
 */
public class ModelEditor extends AceEditor implements ModelListener {
	
	private boolean isReadOnly = false;
	private final ModelManager modelManager;
	private final String fontSize = "10pt";
	
	/** boolean tells if init has been called */
//	private boolean init = false;
		
	public ModelEditor(ModelManager manager){
		super(true);
		this.modelManager = manager;
		modelManager.addModelListener(this);
		
		addAttachHandler(new Handler() {

			@Override
			public void onAttachOrDetach(AttachEvent event) {
				if (event.isAttached()) {
					init();
					activeModelChanged(modelManager.getActiveModel(), false);
					addOnChangeHandler(new AceEditorCallback() {
						@Override
						public void invokeAceCallback(JavaScriptObject obj) {
//							modelManager.setCurrentText(getUnformattedString());
							modelManager.setCurrentText(getText());
							modelManager.setCurrentTextFormated(getText());
						}
					});
				}
			}
			
		});
		
	}
	
	private void setModelText(String modelText){
		setText(modelText);
//		modelManager.setCurrentText(getUnformattedString());
		modelManager.setCurrentText(getText());
	}
	
	public void reFormatText(String currentModelText){
		if(modelManager != null){
			if(modelManager.getActiveModel() != null){
				setModelText(currentModelText);
			}
		}
	}
	/**
	 * Gets the model text without formatting.
	 * @return The unformatted model text.
	 */
//	public String getUnformattedString()
//	{
//		if (init) {
//			String formatted = getText();
//			return formatted.replace("\n", "").replace("\t", "");
//		} else {
//			return "";
//		}
//	}
	
	public void setReadOnly(){
		isReadOnly = true;
	}
	
	private void init(){
		startEditor();
		setMode(AceEditorMode.LPIMODEL);
		// Set the theme of the editor. (Selected theme must have been added as a script tag as specified above.)
		setTheme(AceEditorTheme.ECLIPSE);
		setShowPrintMargin(false);
		setHighlightSelectedWord(true);
		setFontSize(fontSize);
		if(isReadOnly){
			setReadOnly(true);
		}
//		init = true;
	}

	@Override
	public void activeModelChanged(ModelInfo model, boolean getObjects) {
		String modelText = "";
		if (model != null) {
			modelText = reformatText(model.getModelText());
		}	
		setModelText(modelText);
	}

	public String reformatText(String modelText) {
		modelText = modelText.replace("\\\\n", "\n");
		modelText = modelText.replace("\\n", "\n");
		modelText = modelText.replace("\\t", "\t");
		modelText = modelText.replace("\\r", "\r");
		return modelText;
	}
	
	
}
